#include "set_int.h"

#define BOOST_AUTO_TEST_MAIN
#define BOOST_TEST_DYN_LINK

#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_tools.hpp>

#include <boost/assign/std/vector.hpp>

using namespace std;
using namespace boost::assign;

BOOST_AUTO_TEST_CASE(throwTesting) {
    MaxValueSet<10> cset;
    BOOST_CHECK_THROW(cset.add(11), maps::Exception);
    BOOST_CHECK_THROW(cset.del(11), maps::Exception);
    BOOST_CHECK_THROW(cset.del(5) , maps::Exception);

    BOOST_CHECK_NO_THROW(cset.add(5));
    BOOST_CHECK_NO_THROW(cset.del(5));
    BOOST_CHECK_THROW(cset.del(5), maps::Exception);
    BOOST_CHECK_THROW(cset.change(5, 7), maps::Exception);
}

BOOST_AUTO_TEST_CASE(throwTestingMinOutValueSet) {
    MinOutValueSet<10> cset;
    BOOST_CHECK_THROW(cset.add(11), maps::Exception);
    BOOST_CHECK_THROW(cset.del(11), maps::Exception);
    BOOST_CHECK_THROW(cset.del(5) , maps::Exception);

    BOOST_CHECK_NO_THROW(cset.add(5));
    BOOST_CHECK_NO_THROW(cset.del(5));
    BOOST_CHECK_THROW(cset.del(5), maps::Exception);
    BOOST_CHECK_THROW(cset.change(5, 7), maps::Exception);
}

BOOST_AUTO_TEST_CASE(easyTest) {
    MaxValueSet<10> cset;
    BOOST_CHECK_EQUAL(cset.maxValue(), 0);
    for(size_t i = 0; i <= 10; ++i) {
        cset.add(i);
        BOOST_CHECK_EQUAL(cset.maxValue(), i);
    }
    for(size_t i = 0; i < 10; ++i) {
        cset.del(i);
        BOOST_CHECK_EQUAL(cset.maxValue(), 10);
    }
    cset.del(10);
    BOOST_CHECK_EQUAL(cset.maxValue(), 0);

    for(size_t i = 0; i <= 10; ++i) {
        cset.add(i);
        BOOST_CHECK_EQUAL(cset.maxValue(), i);
    }
    for(size_t i = 0; i < 10; ++i) {
        cset.del(10 - i);
        BOOST_CHECK_EQUAL(cset.maxValue(), 9 - i);
    }
    cset.del(0);
    BOOST_CHECK_EQUAL(cset.maxValue(), 0);
}

BOOST_AUTO_TEST_CASE(easyTestMinOutValueSet) {
    MinOutValueSet<10> cset;
    BOOST_CHECK_EQUAL(cset.minOutside(), 0);
    for(size_t i = 0; i <= 10; ++i) {
        cset.add(i);
        BOOST_CHECK_EQUAL(cset.minOutside(), i + 1);
    }
    for(size_t i = 0; i <= 10; ++i) {
        cset.del(i);
        BOOST_CHECK_EQUAL(cset.minOutside(), 0);
    }

    for(size_t i = 0; i <= 10; ++i) {
        cset.add(i);
        BOOST_CHECK_EQUAL(cset.minOutside(), i + 1);
    }
    for(size_t i = 0; i <= 10; ++i) {
        cset.del(10 - i);
        BOOST_CHECK_EQUAL(cset.minOutside(), 10 - i);
    }
}


BOOST_AUTO_TEST_CASE(delAddTest) {
    MaxValueSet<10> cset;
    cset.add(5);
    BOOST_CHECK_EQUAL(cset.maxValue(), 5);

    for(size_t i = 0; i <= 10; ++i) {
        cset.add(10);
        BOOST_CHECK_EQUAL(cset.maxValue(), 10);
        cset.del(10);
        BOOST_CHECK_EQUAL(cset.maxValue(), 5);
    }

    for(size_t i = 0; i <= 10; ++i) {
        cset.add(10);
        BOOST_CHECK_EQUAL(cset.maxValue(), 10);
    }

    for(size_t i = 0; i < 10; ++i) {
        cset.del(10);
        BOOST_CHECK_EQUAL(cset.maxValue(), 10);
    }
    cset.del(10);
    BOOST_CHECK_EQUAL(cset.maxValue(), 5);
}

BOOST_AUTO_TEST_CASE(delAddTestMinOutValueSet) {
    MinOutValueSet<10> cset;
    cset.add(0);
    cset.add(1);
    cset.add(2);
    BOOST_CHECK_EQUAL(cset.minOutside(), 3);

    for(size_t i = 0; i <= 10; ++i) {
        cset.add(10);
        BOOST_CHECK_EQUAL(cset.minOutside(), 3);
        cset.del(10);
        BOOST_CHECK_EQUAL(cset.minOutside(), 3);
    }

    for(size_t i = 0; i <= 10; ++i) {
        cset.add(3);
        BOOST_CHECK_EQUAL(cset.minOutside(), 4);
        cset.del(3);
        BOOST_CHECK_EQUAL(cset.minOutside(), 3);
    }

    for(size_t i = 0; i <= 10; ++i) {
        cset.add(3);
        BOOST_CHECK_EQUAL(cset.minOutside(), 4);
    }

    for(size_t i = 0; i < 10; ++i) {
        cset.del(3);
        BOOST_CHECK_EQUAL(cset.minOutside(), 4);
    }
    cset.del(3);
    BOOST_CHECK_EQUAL(cset.minOutside(), 3);
}


BOOST_AUTO_TEST_CASE(changeTest) {
    MaxValueSet<10> cset;
    cset.add(5);
    BOOST_CHECK_EQUAL(cset.maxValue(), 5);
    
    cset.change(5, 10);
    BOOST_CHECK_EQUAL(cset.maxValue(), 10);
    cset.change(10, 3);
    BOOST_CHECK_EQUAL(cset.maxValue(), 3);
    cset.add(5);
    BOOST_CHECK_EQUAL(cset.maxValue(), 5);
    cset.change(3, 4);
    BOOST_CHECK_EQUAL(cset.maxValue(), 5);
    cset.change(4, 7);
    BOOST_CHECK_EQUAL(cset.maxValue(), 7);
}

BOOST_AUTO_TEST_CASE(changeTestMinOutValueSet) {
    MinOutValueSet<10> cset;
    cset.add(0);
    cset.add(1);
    cset.add(2);
    cset.add(3);
    BOOST_CHECK_EQUAL(cset.minOutside(), 4);

    cset.change(3, 5);
    BOOST_CHECK_EQUAL(cset.minOutside(), 3);
    cset.change(5, 3);
    BOOST_CHECK_EQUAL(cset.minOutside(), 4);
    cset.add(4);
    BOOST_CHECK_EQUAL(cset.minOutside(), 5);
    cset.change(3, 4);
    BOOST_CHECK_EQUAL(cset.minOutside(), 3);
    cset.change(4, 7);
    BOOST_CHECK_EQUAL(cset.minOutside(), 3);
    cset.change(4, 3);
    BOOST_CHECK_EQUAL(cset.minOutside(), 4);

}

BOOST_AUTO_TEST_CASE(overflowTestMinOutValueSet) {
    MinOutValueSet<10> cset;
    for(size_t i = 0; i <= 10; ++i) {
        cset.add(i);
        BOOST_CHECK_EQUAL(cset.minOutside(), i + 1);
    }
    for(size_t i = 0; i <= 10; ++i) {
        cset.add(i);
        BOOST_CHECK_EQUAL(cset.minOutside(), 11);
    }
}
